import { _decorator, Component, Node, Sprite, tween, UITransform, v3 } from 'cc';
import { ImgManager, TCardId } from './ImgManager';
const { ccclass, property } = _decorator;

@ccclass('GameRoot')
export class GameRoot extends Component {
  @property(ImgManager) imgManager: ImgManager;
  @property(Node) pointRoot: Node;

  cards: TCardId[] = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]; // 初始化的牌堆

  currentOpenCard = { node: null, id: -1 }; // 当前打开的牌
  turningCardNum = 0; // 正在翻转的牌的数量

  async start() {
    this.orderCards();
    this.createAllCards();
    await this.moveAllCards();
    await this.setAllCardBeiAnim();
    this.addCardsEvent();
  }

  // 打乱牌堆
  orderCards() {
    this.cards.sort(() => Math.random() - 0.5);
    this.cards.sort(() => Math.random() - 0.5);
    this.cards.sort(() => Math.random() - 0.5);
    console.log(`[Log] this.cards-->`, this.cards);
  }

  // 创建
  createAllCards() {
    this.cards.forEach((cardId) => {
      this.createOneCard(cardId);
    });
  }

  // 创建
  createOneCard(cardId) {
    const cardNode = new Node('card'); // 创建一个 node 节点
    this.node.addChild(cardNode); // 加到当前组件下
    const transform = cardNode.addComponent(UITransform); // 添加位置组件
    const sprite = cardNode.addComponent(Sprite); // 添加图片组件
    sprite.sizeMode = Sprite.SizeMode.CUSTOM;
    transform.setContentSize(140, 200);

    const cardSF = this.imgManager.getCardSFById(cardId);
    sprite.spriteFrame = cardSF; // 设置图片
  }

  // 移动牌堆
  moveAllCards() {
    return new Promise<void>((resolve) => {
      this.node.children.forEach((cardNode, index) => {
        const { x, y } = this.pointRoot.children[index].position;
        tween(cardNode)
          .delay(0.05 * index)
          .to(0.5, { position: v3(x, y, 0) })
          .start();
        // cardNode.setPosition(x, y);
      });
      this.scheduleOnce(() => {
        // 显示2s 后在执行下一步
        resolve();
      }, 2);
    });
  }

  // 翻转为牌背
  setAllCardBeiAnim() {
    return new Promise<void>((resolve) => {
      this.node.children.forEach((cardNode) => {
        tween(cardNode)
          .to(0.5, { scale: v3(0, 1, 1) }) // x轴 缩放0
          .call(() => {
            // 翻转为牌背
            const cardBackSF = this.imgManager.getCardBackSF();
            cardNode.getComponent(Sprite).spriteFrame = cardBackSF;
          }) // x轴 缩放还原
          .to(0.5, { scale: v3(1, 1, 1) })
          .start();
      });
      this.scheduleOnce(() => {
        resolve();
      }, 1);
    });
  }

  addCardsEvent() {
    this.node.children.forEach((cardNode, index) => {
      cardNode.on(
        Node.EventType.TOUCH_END,
        async () => {
          if (cardNode === this.currentOpenCard.node) {
            // 两次点击的是同一个节点，不处理
            return;
          }
          if (this.turningCardNum >= 2) {
            return;
          }
          this.turningCardNum += 1;
          const id = this.cards[index];
          if (!this.currentOpenCard.node) {
            // 第一次点击，记录当前牌
            this.currentOpenCard = { node: cardNode, id }; // 记录当前打开的牌
            this.markCardTurn(cardNode, false, id);
          } else {
            // 第二次点击
            await this.markCardTurn(cardNode, false, id);
            await this.sleep(0.2);
            if (this.currentOpenCard.id === id) {
              // 配对成功
              this.currentOpenCard.node.active = false;
              cardNode.active = false;
            } else {
              // 配对失败
              this.markCardTurn(this.currentOpenCard.node, true);
              await this.markCardTurn(cardNode, true);
            }
            this.currentOpenCard = { node: null, id: -1 }; // 重置 打开的牌
            this.turningCardNum -= 2;
          }
        },
        this
      );
    });
  }

  /**
   * 翻转卡片
   * @param cardNode 卡片节点
   * @param isBack 是否是 翻转到背面
   * @param cardId 卡片id
   */
  markCardTurn(cardNode, isBack, cardId?) {
    return new Promise<void>((resolve) => {
      tween(cardNode)
        .to(0.25, { scale: v3(0, 1, 1) })
        .call(() => {
          const cardSF = isBack ? this.imgManager.getCardBackSF() : this.imgManager.getCardSFById(cardId);
          cardNode.getComponent(Sprite).spriteFrame = cardSF;
        })
        .to(0.25, { scale: v3(1, 1, 1) })
        .call(() => {
          resolve();
        })
        .start();
    });
  }

  sleep(time) {
    return new Promise<void>((resolve) => {
      this.scheduleOnce(() => {
        resolve();
      }, time);
    });
  }

  update(deltaTime: number) {}
}
